#!/bin/bash
#Author: YangYi
#Date: 2025-04-01
#Version: v1
#Content 一键诊断、处置原子能力，集群健康状态检测
#1. 集群检测-节点状态
#2. 集群检测-核心Pod状态
#3. 集群检测-控制平面组件健康
#4. 集群检测-API响应延迟,平均响应 <500ms
#5. 集群检测-事件告警,无持续异常事件

#Date: 2025-04-05
#Version: v2
#Content 输出转化为json格式

# ---------------------------初始化全局变量----------------------------

# 颜色定义
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
NC='\033[0m'

# 从kubeconfig获取token
CURRENT_CONTEXT=$(kubectl config current-context)
#echo "CURRENT_CONTEXT======" $CURRENT_CONTEXT
USER=$(kubectl config view -o jsonpath="{.contexts[?(@.name == '${CURRENT_CONTEXT}')].context.user}")
#echo "USER======" $USER
#TOKEN=$(kubectl config view -o jsonpath="{.users[?(@.name == '${USER}')].user.token}")
#TOKEN=$(kubectl get secret $(kubectl get sa default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode)
TOKEN=$(kubectl get secret -n kube-system $(kubectl get sa -n kube-system kubectl -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode)
#echo "TOKEN======" $TOKEN

# token检查
if [ -z "$TOKEN" ]; then
    echo -e "${RED}错误：无法从kubeconfig获取token，请检查配置${NC}"
    exit 1
fi

# 用户输入
if [ -z "$1" ]; then
    echo "Usage: $0 <请输入您需要诊断的节点IP: 10.145.xxx.xxx>"
    exit 1
fi

# 获取master节点IP
#read -p "请输入master节点IP: " MASTER_IP

# 节点IP获取
#MASTER_IP=$1
MASTER_IP="10.145.218.31"

#返回值
CODE="200"

# ----------------------------功能模块函数-----------------------------

# 检查节点状态
check_nodes() {
 
    local api_url="https://${MASTER_IP}:6443/api/v1/nodes"
    #echo "api_url======" $api_url
    local response=$(curl -k -s -H "Authorization: Bearer $TOKEN" "$api_url")
    #echo "response======" $response
    
    if [ $? -ne 0 ]; then
        echo -e "${RED}无法获取节点信息${NC}"
        return 1
    fi
    #echo -e "\n${YELLOW}=== 节点状态检查 ===${NC}"
    output=$(echo "$response" | jq -r '.items[] | {
        ip: .status.addresses[] | select(.type == "InternalIP").address,
        status: .status.conditions[] | select(.type == "Ready").status
    } | "\(.ip) \(.status)"' | while read -r line; do
        ip=$(echo "$line" | awk '{print $1}')
        status=$(echo "$line" | awk '{print $2}')
        
        if [ "$status" != "True" ]; then
            echo -e "{\"node\": \"${ip}\", \"status\": "1"},"
        else
            echo -e "{\"node\": \"${ip}\", \"status\": "0"},"
        fi
done)
    echo $output | sed '$ s/,$//'
    
    
}

# 检查核心Pod状态
check_core_pods() {
    local api_url="https://${MASTER_IP}:6443/api/v1/pods"
    local response=$(curl -k -s -H "Authorization: Bearer $TOKEN" "$api_url")
    
    if [ $? -ne 0 ]; then
        echo -e "${RED}无法获取Pod信息${NC}"
        return 1
    fi

    #echo -e "\n${YELLOW}=== 核心Pod状态检查 ===${NC}"
    #echo "$response" | jq -r '.items[]  | "\(.metadata.name) \(.metadata.namespace) \(.status.conditions[1].status)"' | while read -r line; do
    output=$(echo "$response" | jq -r '.items[]  | "\(.metadata.name) \(.metadata.namespace) \(.status.conditions[1].status)"' | grep "ccse-api\|coredns\|migrateout" | while read -r line; do
    #echo "$response" | jq -r '.items[]  | "\(.metadata.name) \(.metadata.namespace) \(.status.phase)"' | grep "ccse-api\|coredns\|migrateout" | while read -r line; do
        name=$(echo "$line" | awk '{print $1}')
        namespace=$(echo "$line" | awk '{print $2}')
        status=$(echo "$line" | awk '{print $3}')
        
        #if [ "$status" != "Running" ]; then
        if [ "$status" == "True" ]; then
            echo -e "{\"namespace\": \"${namespace}\", \"name\": \"${name}\", \"status\": "0"},"
        else
	    echo -e "{\"namespace\": \"${namespace}\", \"name\": \"${name}\", \"status\": "1"},"
        fi
done)
    echo $output | sed '$ s/,$//'
    
}

# 检查控制平面组件状态
check_control_plane() {
    #echo -e "\n${YELLOW}=== 控制平面组件状态检查 ===${NC}"

    # 检查controller-manager和scheduler
    local api_url="https://${MASTER_IP}:6443/api/v1/componentstatuses"
    local response=$(curl -k -s -H "Authorization: Bearer $TOKEN" "$api_url")
    
    output1=$(echo "$response" | jq -r '.items[] | select(.metadata.name == "controller-manager" or .metadata.name == "scheduler") | {
        name: .metadata.name,
        status: .conditions[] | select(.type == "Healthy").status
    } | "\(.name) \(.status)"' | while read -r line; do
        component=$(echo "$line" | awk '{print $1}')
        status=$(echo "$line" | awk '{print $2}')
        
        if [ "$status" != "True" ]; then
            echo -e "{\"control_plane_name\": \"${component}\", \"status\": "1"},"
            #echo -e "${RED}组件异常: ${component} - 状态: ${status}${NC}"
        else
            echo -e "{\"control_plane_name\": \"${component}\", \"status\": "0"},"
            #echo -e "${GREEN}组件正常: ${component}${NC}"
        fi
done)
    #echo $output1 | sed '$ s/,$//'
    echo $output1 

    # 检查etcd
    local etcd_url="https://${MASTER_IP}:2379/health"
    output2=$(local etcd_status=$(curl -s --cacert /etc/kubernetes/pki/etcd/ca.crt \
        --cert /etc/kubernetes/pki/etcd/server.crt \
        --key /etc/kubernetes/pki/etcd/server.key \
        https://localhost:2379/health 2>/dev/null | jq -r '.health' 2>/dev/null)
    
    if [ "$etcd_status" != "true" ]; then
        echo -e "{\"control_plane_name\": \"etcd\", \"status\": "1"},"
        #echo -e "${RED}etcd异常: 状态: ${etcd_status:-无法连接}${NC}"
    else
        echo -e "{\"control_plane_name\": \"etcd\", \"status\": "0"},"
        #echo -e "${GREEN}组件正常: etcd${NC}"
	fi)
    echo $output2 | sed '$ s/,$//'
    #echo $output2    
}

# 检查API响应延迟
check_api_latency() {
    #echo -e "\n${YELLOW}=== API响应延迟检查 ===${NC}"
    local api_url="https://${MASTER_IP}:6443/api/v1/namespaces"
    local total_time=0
    local count=5

    for ((i=0; i<count; i++)); do
        response_time=$(curl -k -s -o /dev/null -w "%{time_total}" -H "Authorization: Bearer $TOKEN" "$api_url")
        total_time=$(echo "$total_time + $response_time" | bc)
    done

    output=$(local avg_time=$(echo "scale=3; $total_time / $count" | bc)
    #echo -e "平均响应时间: ${avg_time}秒"
    
    if (( $(echo "$avg_time < 0.5" | bc -l) )); then
        echo -e "{\"name\": \"api_status\", \"status\": "0"}"
        #echo -e "${GREEN}API响应延迟正常${NC}"
        return 0
    else
        echo -e "{\"name\": \"api_status\", \"status\": "1"}"
        #echo -e "${RED}API响应延迟异常: 平均响应时间超过500ms${NC}"
        return 1
	fi)
    echo $output     

}


# 主执行逻辑
main() {
    
    echo -e "${GREEN}开始检查集群状态...${NC}"
    #check_nodes 
    #check_core_pods 
    #check_control_plane 
    #check_api_latency 
    

    local nodes_json=$(check_nodes)
    local core_pods_json=$(check_core_pods)
    local control_plane_json=$(check_control_plane)
    local api_latency_json=$(check_api_latency)

    # 生成JSON报告
    output=$(cat <<EOF
{
  "Global_status": [
    {
    "node_status": [
       $nodes_json  
    ],
    "core_pods_status": [
       $core_pods_json  
    ],
    "control_plane_status": [
       $control_plane_json
    ],
    "api_latency_status": [
       $api_latency_json
    ]
    }
  ],
  "timestamp": "$(date +'%Y-%m-%d %H:%M:%S')",
  "code": "200"
}
EOF
)
echo "$output" | jq . 

}

# 执行主函数
main
